from asyncio import FastChildWatcher
from cgi import test
from code import interact
from collections import deque
from gc import collect
import os
import time
import numpy as np
from isaacgym import gymutil
from isaacgym import gymapi
#from isaacgym import gymtorch
from math import sqrt
import math
from sympy import false
import cv2
from draw import *
from pcgworker.PCGWorker import *

from wfc_vecenv_stable_baselines import PCGVecEnvStableBaselines
from wfc_env import *

from stable_baselines3 import PPO
from stable_baselines3.common.callbacks import BaseCallback
from stable_baselines3.common.results_plotter import load_results, ts2xy
from stable_baselines3.common.monitor import Monitor
from stable_baselines3.common import results_plotter
from stable_baselines3.common.results_plotter import load_results, ts2xy, plot_results
from stable_baselines3.common.noise import NormalActionNoise
from stable_baselines3.common.callbacks import BaseCallback

def seed_distribution(collection : deque):

    distribution_table = [
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
        [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,2],
        [0,0,0,1,1,1,2,2,2,2,2,3,3,3,3,3],
        [0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,4],
        [0,0,1,1,2,2,3,3,3,4,4,4,5,5,5,5],
        [0,1,1,2,2,3,3,4,4,5,5,5,6,6,6,6],
        [0,1,2,2,3,3,4,4,5,5,6,6,7,7,7,7],
        [0,1,2,3,4,4,5,5,6,6,7,7,8,8,8,8],
        [0,1,2,3,4,5,6,6,7,7,8,8,9,9,9,9],
        [0,1,2,3,4,5,6,7,8,8,9,9,10,10,10,10],
        [0,1,2,3,4,5,6,7,8,9,10,10,11,11,11,11],
        [0,1,2,3,4,5,6,7,8,9,10,11,12,12,12,12]
    ]

    print("distribution : ", len(distribution_table))

    collection_size = len(collection)

    if collection_size < 13:
        distribution = copy.deepcopy(distribution_table[collection_size-1])
        arrangement = []
        for i in distribution:
            arrangement.append(-(collection_size-i))
    else:
        distribution = copy.deepcopy(distribution_table[12])
        arrangement = []
        for i in distribution:
            arrangement.append((collection_size-13)-(collection_size-i))
    print("arrangement : ", arrangement)
    collection_ = []
    for i in arrangement:
        collection_.append(collection[i])

    print("collection_ : ", collection_)

    return collection_


test_dq = deque()
test_dq.append(1)

print(test_dq[-1])

seed_collecttion = deque(maxlen=64)

seed_collecttion.append(1)
seed_collecttion.append(2)
seed_collecttion.append(3)
seed_collecttion.append(4)
seed_collecttion.append(5)
seed_collecttion.append(6)
seed_collecttion.append(7)
seed_collecttion.append(8)
seed_collecttion.append(9)
seed_collecttion.append(10)
seed_collecttion.append(11)
seed_collecttion.append(12)
seed_collecttion.append(13)
seed_collecttion.append(14)
seed_collecttion.append(15)
seed_collecttion.append(16)
seed_collecttion.append(17)
seed_collecttion.append(18)


_ = seed_distribution(seed_collecttion)

print(seed_collecttion)

seed_collecttion.pop()
seed_collecttion.pop()
seed_collecttion.pop()
seed_collecttion.pop()

print(seed_collecttion)


# LOGDIR = "./training_logs"
# m_env = Monitor(CustomEnv(headless_ = False,seed_pth = "seed.json"), LOGDIR, allow_early_resets=True)
# observation = m_env.reset()
# model = PPO.load("./training_logs/best_model.zip", env=m_env)

# model1 = PPO('CnnPolicy', env=m_env, batch_size = 1024)
# model1.set_parameters(model.get_parameters())

# del model
# del model1

# # print("model1 : ", model1.get_parameters())

performance_ = [[0.9933333333333333, 0.68], [0.9966666666666667, 0.7766666666666666]]

# increment of success rate, best value is 1
d_sr = performance_[1][1] - performance_[0][1]
# final success rate, best value is 1
sr_final = performance_[1][1]
# (maximum) performance drop on old envs, best value is -1
sr_drop = performance_[0][0] - performance_[1][0]

metrics_ = sqrt((d_sr-1)*(d_sr-1) + (sr_final-1)*(sr_final-1) + (sr_drop+1)*(sr_drop+1))

print("metrics_ : ", metrics_)

metrics_ = [
    (0,1.3137139888287879),
    (1,1.315906953819726),
    (2,1.3035421827552118),
    (3,1.229435281383738),
    (4,1.317080103866124),
    (5,1.2441552243278258),
    (6,1.3798268812507684),
    (7,1.3031713454321943),
    (8,1.3635370670918092),
    (9,1.1857112258518558)
]

metrics_ = sorted(metrics_, key=lambda x: x[1])

for i in metrics_:
    print(i)

''' output:
(9, 1.1857112258518558)
(3, 1.229435281383738)
(5, 1.2441552243278258)
(7, 1.3031713454321943)
(2, 1.3035421827552118)
(0, 1.3137139888287879)
(1, 1.315906953819726)
(4, 1.317080103866124)
(8, 1.3635370670918092)
(6, 1.3798268812507684)
'''


''' output:
(9, 1.1855612829185826)
(8, 1.284739489373451)
(1, 1.296529555732876)
(0, 1.3110682667199294)
(6, 1.318559820410132)
(2, 1.3227622613304328)
(3, 1.3276127280029955)
(7, 1.3332041604095501)
(4, 1.3336208023439213)
(5, 1.3340581363310637)
'''

# pcg_worker = PCGWorker(9,9)

# seed_ = pcg_worker.from_file("0.json")

# # compute entropy of landscape
# entropy_ = pcg_worker.fitness(seed_)

# print("entropy_ : ", entropy_)

# entropies_ = [
#     (0,169.97855994458578),
#     (1,158.8454625440992),
#     (2,145.40461290138862),
#     (3,136.80311414176504),
#     (4,139.67043190239008),
#     (5,176.30954870707947),
#     (6,147.1134907892576),
#     (7,159.03169905578352),
#     (8,157.02718199125334),
#     (9,167.34797712257352)
# ]

# entropies_ = sorted(entropies_, key=lambda x: x[1])

# for i in entropies_:
#     print(i)

# ''' output:
# (3, 136.80311414176504)
# (4, 139.67043190239008)
# (2, 145.40461290138862)
# (6, 147.1134907892576)
# (8, 157.02718199125334)
# (1, 158.8454625440992)
# (7, 159.03169905578352)
# (9, 167.34797712257352)
# (0, 169.97855994458578)
# (5, 176.30954870707947)
# '''


# srs_ = [
#     (0,0.9366666666666666),
#     (1,0.9266666666666666),
#     (2,0.9833333333333333),
#     (3,0.9533333333333334),
#     (4,0.98),
#     (5,0.9133333333333333),
#     (6,0.96),
#     (7,0.9633333333333334),
#     (8,0.9666666666666667),
#     (9,0.8866666666666667)
# ]

# srs_ = sorted(srs_, key=lambda x: x[1], reverse=True)

# print("---------------------------")

# for i in srs_:
#     print(i)

# ''' output:
# (2, 0.9833333333333333)
# (4, 0.98)
# (8, 0.9666666666666667)
# (7, 0.9633333333333334)
# (6, 0.96)
# (3, 0.9533333333333334)
# (0, 0.9366666666666666)
# (1, 0.9266666666666666)
# (5, 0.9133333333333333)
# (9, 0.8866666666666667)
# '''


# sr_log = [
#         [0.79,0.9366666666666666],
#         [0.7566666666666667,0.9266666666666666],
#         [0.8566666666666667,0.9833333333333333],
#         [0.8366666666666667,0.9533333333333334],
#         [0.8733333333333333,0.98],
#         [0.8033333333333333,0.9133333333333333],
#         [0.83,0.96],
#         [0.8366666666666667,0.9633333333333334],
#         [0.7766666666666666,0.9666666666666667],
#         [0.5133333333333333,0.8866666666666667]
#     ]

# sr_log = [
#         [0.75,0.9],
#         [0.8466666666666667,0.98],
#         [0.7933333333333333,0.9433333333333334],
#         [0.64,0.92],
#         [0.86,0.9766666666666667],
#         [0.5333333333333333,0.82],
#         [0.8266666666666667,0.88],
#         [0.7666666666666667,0.93],
#         [0.68,0.7766666666666666],
#         [0.47333333333333333,0.8533333333333334]
#     ]

# # draw sr_log with bar chart
# x = [i for i in range(len(sr_log))]
# y = [i[1] for i in sr_log]
# z = [i[0] for i in sr_log]

# plt.bar(x, y, color='g', label='larva success rate on new env')
# plt.bar(x, z, color='b', label='imago success rate on new env')
# # fix range of vertical axis : 0-1
# plt.ylim(0,1)
# # draw labels on right bottom corner
# plt.legend(loc='lower right')
# # label x axis with "decendent"
# plt.xlabel("decendent")
# # label y axis with "success rate"
# plt.ylabel("success rate")
# plt.show()




# =================================================================================================

# performance_records = [[[0.99, 0.9333333333333333, 0.8166666666666667, 0.77], [0.9933333333333333, 0.95, 0.94, 0.9366666666666666]], [[0.9966666666666667, 0.94, 0.8733333333333333, 0.8366666666666667], [1.0, 0.9633333333333334, 0.93, 0.91]], [[0.99, 0.9666666666666667, 0.8566666666666667, 0.7766666666666666], [0.9933333333333333, 0.9633333333333334, 0.9533333333333334, 0.85]], [[1.0, 0.9466666666666667, 0.8433333333333334, 0.7333333333333333], [0.9966666666666667, 0.9733333333333334, 0.9733333333333334, 0.9366666666666666]], [[0.9966666666666667, 0.96, 0.8166666666666667, 0.8466666666666667], [0.9866666666666667, 0.9633333333333334, 0.93, 0.9566666666666667]], [[0.9933333333333333, 0.9133333333333333, 0.8666666666666667, 0.6766666666666666], [1.0, 0.97, 0.95, 0.9066666666666666]], [[0.9933333333333333, 0.9566666666666667, 0.8666666666666667, 0.47], [0.9933333333333333, 0.96, 0.9433333333333334, 0.88]], [[1.0, 0.9233333333333333, 0.8566666666666667, 0.6566666666666666], [0.99, 0.9666666666666667, 0.95, 0.9]], [[1.0, 0.94, 0.82, 0.74], [1.0, 0.9566666666666667, 0.9533333333333334, 0.9066666666666666]], [[0.9933333333333333, 0.9433333333333334, 0.85, 0.8333333333333334], [0.9966666666666667, 0.9666666666666667, 0.96, 0.9633333333333334]]]

# metrics = []

# print("---------------------")

# evaluation = []
# for i in range(len(performance_records)):

#     larva_eval = performance_records[i][0]
#     adult_eval = performance_records[i][1]

#     # 3.1. maximum performance drop on old maps
#     sr_drop_max = -1000
#     for j in range(len(larva_eval)-1):
#         sr_drop = larva_eval[j] - adult_eval[j]
#         if sr_drop > sr_drop_max:
#             sr_drop_max = sr_drop

#     # 3.2. performance gain on new maps
#     sr_gain = adult_eval[-1] - larva_eval[-1]

#     # 3.3. success rate on new maps
#     sr_new = adult_eval[-1]

#     print("sr_final: ", sr_new, " i : ", i)

#     evaluation.append(copy.deepcopy([sr_drop_max, sr_gain, sr_new]))

# metrics = []
# for i in range(len(evaluation)):
#     score = sqrt((evaluation[i][0]+1)**2 + (evaluation[i][1]-1)**2 + (evaluation[i][2]-1)**2)
#     metrics.append((i, copy.deepcopy(score)))

# metrics = sorted(metrics, key=lambda x: x[1])

# for i in metrics:
#     print(i)


# m_env = PCGVecEnvStableBaselines(headless_ = True)
# # model = PPO('CnnPolicy', env=m_env, batch_size = 1024, device="cuda:1")
# model = PPO('CnnPolicy', env=m_env, batch_size = 1024, device="cuda:0")

# model1 = PPO('CnnPolicy', env=m_env, batch_size = 1024, device="cuda:0")

# # model.device = "cuda:1"

# model_params1 = copy.deepcopy(model1.get_parameters())

# model.set_parameters(model_params1)

# model_params = model.get_parameters()

# print(model_params)


# output_1 = [ (3, 0.0), (4, 0.0), (6, 0.0), (7, 0.0), (8, 0.0),  (5, 0.0),(0, 0.0),(1, 0.0), (2, 0.0), (9, 0.0)]

# print(output_1)
# # re-orgainze output_1 by output_1[:][0]
# output_1 = sorted(output_1, key=lambda x: x[0])

# print(output_1)


# # draw a half circle on an opencv image and display it
# import cv2
# import numpy as np
# # Colors (B, G, R)
# WHITE = (255, 255, 255)
# BLACK = (0, 0, 0)


# def create_blank(width, height, color=(0, 0, 0)):
#     """Create new image(numpy array) filled with certain color in BGR"""
#     image = np.zeros((height, width, 3), np.uint8)
#     # Fill image with color
#     image[:] = color

#     return image


# def draw_half_circle_no_round(image):
#     height, width = image.shape[0:2]
#     # Ellipse parameters
#     radius = 100
#     center = (100,100)
#     axes = (radius, radius)
#     angle = 0
#     startAngle = 0
#     endAngle = -60
#     # When thickness == -1 -> Fill shape
#     thickness = -1

#     # log start time
#     start_time = time.time()
#     # Draw black half circle
#     cv2.ellipse(image, center, axes, angle, startAngle, endAngle, BLACK, thickness)
#     # log end time
#     end_time = time.time()
#     print("draw_half_circle_no_round time: ", end_time - start_time)

#     # axes = (radius - 10, radius - 10)
#     # # Draw a bit smaller white half circle
#     # cv2.ellipse(image, center, axes, angle, startAngle, endAngle, WHITE, thickness)

# # Create new blank 300x150 white image
# width, height = 300, 150

# image = create_blank(width, height, color=WHITE)
# draw_half_circle_no_round(image)
# cv2.imshow("image", image)
# cv2.waitKey(0)


test_dq = deque(maxlen=64)

for i in range(50):
    test_dq.append(i)

# traverse the last 16 elements in the deque
for i in range(min(len(test_dq), 16)):
    i_start = min(len(test_dq), 16)
    print(test_dq[len(test_dq)-(i_start-i)])



for i in range(41):
    for ii in range(8):
        cmd_ = "git rm -r --cached gen_"+str(i)+"_dec_"+str(ii)+".json"
        print(cmd_)

# for i in range(41):
#     cmd_ = "git rm -r --cached performance_records_gen_"+str(i)+".json"
#     print(cmd_)